#include "MatrizAdyacencia.h"

using namespace modelo;

MatrizAdyacencia::MatrizAdyacencia(list<InformacionMateria*> informacionMaterias)
{
	this->Inicializar(informacionMaterias);
};

void MatrizAdyacencia::Inicializar(list<InformacionMateria*> informacionMaterias)
{
	list<InformacionMateria*>::iterator itBase;
	list<InformacionMateria*>::iterator itCorrelativas;
	for(itBase = informacionMaterias.begin(); itBase != informacionMaterias.end(); itBase++)
	{
		string codigoBase = (*itBase)->GetCodigo();
		for(itCorrelativas = informacionMaterias.begin(); itCorrelativas != informacionMaterias.end(); itCorrelativas++)
		{
			string codigoCorrelativa = (*itCorrelativas)->GetCodigo();
			this->matrizCodigos[this->ConstruirKey(codigoBase, codigoCorrelativa)] = false;
		}
	}
};

void MatrizAdyacencia::CalcularRequisitosParaCursar(InformacionMateriaSegunCarrera* informacionMateria)
{
	for(map<string,bool>::iterator it = this->matrizCodigos.begin(); it != this->matrizCodigos.end(); ++it) 
	{
		string key = it->first;
		if(key.find(informacionMateria->GetCodigo() + '|') != std::string::npos && this->matrizCodigos[key])
		{
			int posSeparador = key.find('|');
			string codigoMateriaNecesaria = key.substr(posSeparador + 1, key.length() - posSeparador);
			list<string> codigoMateriasNecesarias = informacionMateria->GetCodigoMateriasNecesarias();
			codigoMateriasNecesarias.push_back(codigoMateriaNecesaria);
			informacionMateria->SetCodigoMateriasNecesarias(codigoMateriasNecesarias);
		}
	}
};

void MatrizAdyacencia::CalcularMateriasPosterioresPara(InformacionMateriaSegunCarrera* informacionMateria)
{
	for(map<string,bool>::iterator it = this->matrizCodigos.begin(); it != this->matrizCodigos.end(); ++it) 
	{
		string key = it->first;
		if(key.find('|' + informacionMateria->GetCodigo()) != std::string::npos && this->matrizCodigos[key])
		{
			int posSeparador = key.find('|');
			string codigoMateriaPosterior = key.substr(0, posSeparador);
			list<string> codigoMateriasPosteriores = informacionMateria->GetCodigoMateriasPosteriores();
			codigoMateriasPosteriores.push_back(codigoMateriaPosterior);
			informacionMateria->SetCodigoMateriasPosteriores(codigoMateriasPosteriores);
		}
	}
};

int MatrizAdyacencia::SumarCorrelativasPara(string codigoMateria)
{
	int sumaCorrelativas = 0;
	for(map<string,bool>::iterator it = this->matrizCodigos.begin(); it != this->matrizCodigos.end(); ++it) 
	{
		string key = it->first;
		if(key.find('|' + codigoMateria) != std::string::npos && this->matrizCodigos[key])
		{
			sumaCorrelativas++;
		}
	}
	return sumaCorrelativas;
};

void MatrizAdyacencia::RegistrarCorrelativa(string codigoMateria, string codigoCorrelativa)
{
	this->matrizCodigos[this->ConstruirKey(codigoMateria, codigoCorrelativa)] = true;
};

string MatrizAdyacencia::ConstruirKey(string codigoBase, string codigoCorrelativa)
{
	return codigoBase + '|' + codigoCorrelativa;
};